-
Notifications
You must be signed in to change notification settings - Fork 8.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement recursive plugin discovery #68811
Implement recursive plugin discovery #68811
Conversation
...scanDirs.map((dir) => `${dir}/*/kibana.json`), | ||
...scanDirs.map((dir) => `${dir}/**/kibana.json`), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comparing this diff with the changes in plugins_discovery.ts
made me cry a little.
Note that the optimizer does not exactly reproduce the logic used in the discovery system:
- It doesn't handle
maxDepth
- It will discover plugins nested inside other plugins
However, I think this is acceptable. Worse case some plugins will be build that are not going to be discovered by core's discovery system. But that would be detected during the development phase anyway. (and implementing the exact same logic would cause findKibanaPlatformPlugins
to become way more complex than its currently is)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wonder if we could have some sort of maxDepth by using a (very unreadable) glob like:
`${dir}/{*,*/*,*/*/*,*/*/*/*,*/*/*/*/*}/kibana.json`
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Either that or
...scanDirs
.map((dir) => [
`${dir}/*/kibana.json`,
`${dir}/*/*/kibana.json`,
`${dir}/*/*/*/kibana.json`,
`${dir}/*/*/*/*/kibana.json`,
`${dir}/*/*/*/*/*/kibana.json`,
])
.flat(),
Which is a little longer (even if it can be extracted to a function), but probably more explicit.
Not 100% sure this is really needed (as it doesn't address the second point), but I have no problem implementing that if we think it's a little better can current implem.
wdyt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's err on the side of caution here and go ahead and do that. Optimizer is already slow as it is, let's be defensive.
// jest relies on the filesystem to get sourcemaps when using console.log | ||
// which breaks with the mocked FS, see https://github.com/tschaub/mock-fs/issues/234 | ||
// hijacking logging to process.stdout as a workaround for this suite. | ||
jest.spyOn(console, 'log').mockImplementation((...args) => { | ||
process.stdout.write(args + '\n'); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Self explicit comment. TIL, jest patches console.log
to add source-map capabilities to the output. But it uses fs.lstat
at some point in the process, and we are mocking the whole FS for this suite.
There is an open issue to implements layering to mock-fs
, but until then, the process.stdout
seems like an acceptable workaround. (This doesn't affect the testing behavior in any way)
mockFs( | ||
{ | ||
[KIBANA_ROOT]: { | ||
src: { | ||
plugins: { | ||
plugin_a: Plugins.valid('pluginA'), | ||
}, | ||
}, | ||
plugins: { | ||
plugin_b: Plugins.valid('pluginB'), | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why mock-fs
:
- Better test data isolation. The mocked FS is described in each test, which makes it way easier to understand what we are doing that having to see the content of a fixture folder (at least ihmo)
- ATM, we don't have any tool to mock the
Env
class, and thepluginSearchPaths
are hardcoded in it's constructor, meaning thatdiscover
will necessarily scan{cwd}/src/plugins
. We can't have it use another root folder without dirty tricks.mock-fs
allow to easily mock the content of thekibana
directory - More powerful than persistent test folders committed in the repository (can define permissions on a file/folder in the fs definition for example. Doing the same on a real FS always leads to troubles)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO it's a bit easier to grok this if we used regular directory paths as keys rather than nested objects (which mock-fs supports):
mockFs({
[KIBANA_ROOT]: {
'src/plugins/plugin_a': Plugins.valid('pluginA'),
'plugins/plugin_b': /** */,
'x-pack/plugins/plugin_c': /** */,
}
})
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's supposed to, however I'm having failures when running your changes.
When looking at the actual implementation of mock-fs
's filesystem, it seems the populate
logic does not accept nested multi-path keys (...)
This works:
mockFs(
{
[`${KIBANA_ROOT}/src/plugins/plugin_a`]: Plugins.valid('pluginA'),
[`${KIBANA_ROOT}/plugins/plugin_b`]: Plugins.valid('pluginB'),
},
{ createCwd: false }
);
but this doesn't:
mockFs(
{
[KIBANA_ROOT]: {
'src/plugins/plugin_a': Plugins.valid('pluginA'),
'plugins/plugin_b': Plugins.valid('pluginB'),
},
},
{ createCwd: false }
);
wdyt? Do we still prefer the long
[`${KIBANA_ROOT}/src/plugins/plugin_a`]: Plugins.valid('pluginA'),
syntax over the one currently used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that would be slight more clear, yes.
Pinging @elastic/kibana-platform (Team:Platform) |
@pgayvallet Out of curiosity, as described by #59189 this doesn't support plugins inside of plugins right? (kind of implied by "recursive plugin discovery") |
Right. The PR title might be a little misleading. It scans sub-directories until it finds a plugin, and then won't go further on this specific branch. (Even if this specific rule is not 'respected' by the way i modified the optimizer, see #68811 (comment)) |
…ve-plugin-discovery
…ve-plugin-discovery
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kbn/optimizer
changes LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested locally without any issues. A few comments, but no major problems stood out to me.
...scanDirs.map((dir) => `${dir}/*/kibana.json`), | ||
...scanDirs.map((dir) => `${dir}/**/kibana.json`), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wonder if we could have some sort of maxDepth by using a (very unreadable) glob like:
`${dir}/{*,*/*,*/*/*,*/*/*/*,*/*/*/*/*}/kibana.json`
mockFs( | ||
{ | ||
[KIBANA_ROOT]: { | ||
src: { | ||
plugins: { | ||
plugin_a: Plugins.valid('pluginA'), | ||
}, | ||
}, | ||
plugins: { | ||
plugin_b: Plugins.valid('pluginB'), | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO it's a bit easier to grok this if we used regular directory paths as keys rather than nested objects (which mock-fs supports):
mockFs({
[KIBANA_ROOT]: {
'src/plugins/plugin_a': Plugins.valid('pluginA'),
'plugins/plugin_b': /** */,
'x-pack/plugins/plugin_c': /** */,
}
})
|
||
await expect( | ||
error$ | ||
it('return errors when the plugin search path is not accessible', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we have a similar test for if the kibana.json
file is inaccessible?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added. However even in 000
mode, the stat
operation returns in success (which is normal). The error is therefor catched a little late, in parseManifest
. It's probably still acceptable (and I don't really want to perform a try-read just to catch the error sooner)
const manifestPath = (...pluginPath: string[]) => | ||
resolve(KIBANA_ROOT, 'src', 'plugins', ...pluginPath, 'kibana.json'); | ||
|
||
describe('plugins discovery system', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we have a test that uses symlinks? I think that's probably a common use-case for 3rd party plugins. Good news is it looks like mock-fs supports symlinks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you have in mind exactly? A symlink from a nested plugin directory to an arbitrary other path on the FS containing the plugin files?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Main use case doesn't really have to do with nested directories, but I think it's probably common for deployments to symlink the <kibana root>/plugins
directory for custom plugins.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added test
…ve-plugin-discovery
…ve-plugin-discovery
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM after #68811 (comment) and #68811 (comment) are resolved. Lots of interest in this change, it's going be very helpful!
retest |
…ve-plugin-discovery
…ve-plugin-discovery
💚 Build SucceededBuild metrics
History
To update your PR or re-run it, just comment with: |
* implements recursive scanning in plugin discovery system * update optimizer to find plugins in sub-directories * update renovate * update optimizer IT snapshot * refactor processPluginSearchPaths$ and add test for inaccessible manifest * add symlink test * add maxDepth to the optimizer * adapt mockFs definitions * remove `flat` usage # Conflicts: # renovate.json5
* implements recursive scanning in plugin discovery system * update optimizer to find plugins in sub-directories * update renovate * update optimizer IT snapshot * refactor processPluginSearchPaths$ and add test for inaccessible manifest * add symlink test * add maxDepth to the optimizer * adapt mockFs definitions * remove `flat` usage # Conflicts: # renovate.json5
…ata-streams * 'master' of github.com:elastic/kibana: (50 commits) [Logs UI] [Alerting] "Group by" functionality (elastic#68250) [Discover] Deangularize Skip to bottom button (elastic#69811) Implement recursive plugin discovery (elastic#68811) Use ts-expect-error in platform code (elastic#69883) [SIEM][Detection Engine][Lists] Moves getQueryFilter to common folder for use by both front and backend [Ingest Manager][SECURITY SOLUTION] adjust config reassign link and add roundtrip to Reassignment flow (elastic#70208) [Security][Lists] Add API functions and react hooks for value list APIs (elastic#69603) [ILM] Fix bug when clearing priority field (elastic#70154) [Platform][Security] Updates cluster_manager ignorePaths to include security scripts (elastic#70139) [IngestManager] Allow to filter agent by packages (elastic#69731) [code coverage] exclude folders: test_helpers, tests_bundle (elastic#70199) [Metrics UI] UX improvements for saved views (elastic#69910) [APM] docs: unique transaction troubleshooting (elastic#69831) Cross cluster search functional test with minimun privileges assigned to the test_user (elastic#70007) [Maps] choropleth layer wizard (elastic#69699) Make custom errors by extending Error (elastic#69966) [Ingest Manager] Support updated package output structure (elastic#69864) Resolver test coverage (elastic#70246) Async Discover search test (elastic#64388) [ui-shared-deps] include styled-components (elastic#69322) ... # Conflicts: # x-pack/plugins/snapshot_restore/server/types.ts
…bana into alerting/consumer-based-rbac * 'alerting/consumer-based-rbac' of github.com:gmmorris/kibana: (49 commits) [Discover] Deangularize Skip to bottom button (elastic#69811) Implement recursive plugin discovery (elastic#68811) Use ts-expect-error in platform code (elastic#69883) [SIEM][Detection Engine][Lists] Moves getQueryFilter to common folder for use by both front and backend [Ingest Manager][SECURITY SOLUTION] adjust config reassign link and add roundtrip to Reassignment flow (elastic#70208) [Security][Lists] Add API functions and react hooks for value list APIs (elastic#69603) [ILM] Fix bug when clearing priority field (elastic#70154) [Platform][Security] Updates cluster_manager ignorePaths to include security scripts (elastic#70139) [IngestManager] Allow to filter agent by packages (elastic#69731) [code coverage] exclude folders: test_helpers, tests_bundle (elastic#70199) [Metrics UI] UX improvements for saved views (elastic#69910) [APM] docs: unique transaction troubleshooting (elastic#69831) Cross cluster search functional test with minimun privileges assigned to the test_user (elastic#70007) [Maps] choropleth layer wizard (elastic#69699) Make custom errors by extending Error (elastic#69966) [Ingest Manager] Support updated package output structure (elastic#69864) Resolver test coverage (elastic#70246) Async Discover search test (elastic#64388) [ui-shared-deps] include styled-components (elastic#69322) SECURITY-ENDPOINT: add host properties (elastic#70238) ...
* implements recursive scanning in plugin discovery system * update optimizer to find plugins in sub-directories * update renovate * update optimizer IT snapshot * refactor processPluginSearchPaths$ and add test for inaccessible manifest * add symlink test * add maxDepth to the optimizer * adapt mockFs definitions * remove `flat` usage
Summary
Fix #59189
Update core plugin discovery system and the kibana platform optimizer to look for plugin in sub directories.
Checklist